package com.slt.concurrency.mashibing2019.Interview.exorcise02;

import java.util.LinkedList;
import java.util.concurrent.TimeUnit;

/**
 * 写一个固定容量同步容器，拥有put和get方法，
 * 能够支持2个生产者线程以及10个消费者线程的阻塞调用
 *
 * 实现一个阻塞队列
 * 生产者和消费者不能同时工作，因为是synchronized修饰的方法
 */
public class MyContainer1<T> {
	final private LinkedList<T> lists = new LinkedList<>();
	final private int MAX = 10; //���10��Ԫ��
	private int count = 0;
	
	
	public synchronized void put(T t) {
		//为什么用while不用if
		while(lists.size() == MAX) {
			try {
				this.wait(); //effective java
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		lists.add(t);
		++count;
		this.notifyAll();
	}
	//消费动作
	public synchronized T get() {
		T t = null;
		while(lists.size() == 0) {
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		t = lists.removeFirst();
		count --;
		this.notifyAll(); //
		return t;
	}
	
	public static void main(String[] args) {
		MyContainer1<String> c = new MyContainer1<>();
		//10个消费者线程
		for(int i=0; i<10; i++) {
			new Thread(()->{
				for(int j=0; j<5; j++) {
					System.out.println(Thread.currentThread().getName() + "消费了： " + c.get());
				}
			}, "c" + i).start();
		}
		
		try {
			TimeUnit.SECONDS.sleep(2);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		//两个生产者线程
		for(int i=0; i<2; i++) {
			new Thread(()->{
				for(int j=0; j<25; j++){
					c.put(Thread.currentThread().getName() + " " + j);
					System.out.println(Thread.currentThread().getName() + " " + j);
				}
			}, "p" + i).start();
		}
	}
}
